package br.edu.ufcg.dsc.psoo.mymoney.controller.implementation;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import br.edu.ufcg.dsc.psoo.mymoney.controller.TypeController;
import br.edu.ufcg.dsc.psoo.mymoney.controller.Validator;
import br.edu.ufcg.dsc.psoo.mymoney.controller.exceptions.InvalidTypeException;
import br.edu.ufcg.dsc.psoo.mymoney.controller.exceptions.TypeNotFoundException;
import br.edu.ufcg.dsc.psoo.mymoney.model.bean.Type;
import br.edu.ufcg.dsc.psoo.mymoney.model.bean.User;
import br.edu.ufcg.dsc.psoo.mymoney.model.dao.TypeDAO;
import br.edu.ufcg.dsc.psoo.mymoney.model.hibernate.HibernateUtil;

/**
 * Controller respons�vel pela valida��o e opera��es envolvendo tipos
 * 
 * @author leonardo
 * 
 */
public class TypeControllerImpl implements TypeController {
	private TypeDAO typeDAO;
//	private SessionFactory sf;
	public static final SessionFactory sf = HibernateUtil.getSessionFactory();
	private Session session;

	private Validator validator = new Validator();

	/**
	 * Construtor padrao recebendo o DAO de Type via Injection (Mentawai)
	 * 
	 * @param typeDAO
	 */
	public TypeControllerImpl(TypeDAO typeDAO) {
		this.typeDAO = typeDAO;
	}

	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.TypeC#closeSession()
	 */
	public void closeSession() {
		session.close();
		typeDAO.setSession(session);
	}

	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.TypeC#create(br.edu.ufcg.dsc.psoo.mymoney.model.bean.Type)
	 */
	public Type create(Type type) throws InvalidTypeException {
		openSession();
		// campos em branco
		if (type.getName().equals("") || type.getUser() == null) {
			// campos obrigatórios
			throw new InvalidTypeException("Preencha todos os campos!");
		} else {
			if (type.getName().equals("Debito")
					|| type.getName().equals("Credito")) {
				throw new InvalidTypeException("Tipos padroes Credito e Debito ja registrados!");
			} else {
				if ((typeDAO.findByName(type.getName())) != null) {
					throw new InvalidTypeException(
							"Nome ja registrado!");
				} else {
					if (!validator.alfanumericValidator(type.getName(), 3, 20)) {
						throw new InvalidTypeException("Nome invalido!");
					}
				}
			}

			// persiste no banco o novo usuário
			Type createdType = typeDAO.create(type);
			closeSession();

			return createdType;
		}
	}

	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.TypeC#delete(java.lang.Long, java.lang.Long)
	 */
	public void delete(Long id, Long userId) throws InvalidTypeException,
			TypeNotFoundException {
		openSession();

		Type type = new Type();
		type.setId(id);

		if (id == null)
			throw new TypeNotFoundException("Tipo nao encontrado!");
		else {
			Type bdType = typeDAO.load(type.getId());
			if ((bdType != null)
					&& (bdType.getName().equals("Debito") || bdType.getName()
							.equals("Credito"))) {
				throw new InvalidTypeException(
						"Impossivel apagar os tipos pre-definidos Debito e Credito!");
			} else {
				if (!bdType.getUser().getId().equals(userId)) {
					throw new InvalidTypeException(
							"You don't have permission to delete this type!");
				} else {
					typeDAO.delete(bdType);
				}
			}
		}
		closeSession();
	}

	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.TypeC#openSession()
	 */
	public void openSession() {
		session = sf.openSession();
		typeDAO.setSession(session);
	}

	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.TypeC#listAll(java.lang.Long)
	 */
	public List<Type> listAll(Long userId) {
		openSession();
		Type t = new Type();
		User u = new User();
		
		u.setId(new Long(1));
		t.setUser(u);
		List<Type> preDefinedOnes = typeDAO.find(t);
		
		u.setId(userId);
		t.setUser(u);
		List<Type> result = typeDAO.find(t);
		
		preDefinedOnes.addAll(result);
		closeSession();
		return preDefinedOnes;
	}
	/* (non-Javadoc)
	 * @see br.edu.ufcg.dsc.psoo.mymoney.controller.TypeC#update(br.edu.ufcg.dsc.psoo.mymoney.model.bean.Type)
	 */
	public Type update(Type type) throws InvalidTypeException {
		
		// campos em branco
		if (type.getUser() == null) {
			throw new InvalidTypeException("Username invalido!");
		} else {
			if (type.getName().equals("")) {
				// campos obrigatórios
				throw new InvalidTypeException("Preencha todos os campos!");
			} else {
				if (type.getName().equals("Debito")
						|| type.getName().equals("Credito")) {
					throw new InvalidTypeException("Tipos padroes Credito e Debito ja registrados!");
				} else {
					 if (type.getId().equals(new Long("1")) || type.getId().equals(new Long("2"))) {
					 throw new
					 InvalidTypeException("Este tipo padrao nao pode ser alterado!");
					 }
					 else {
						 openSession();
						 Type bdType = typeDAO.findByName(type.getName());
						 closeSession();
					if (bdType != null && !type.getId().equals(bdType.getId())) {
						throw new InvalidTypeException(
								"Nome ja registrado!");
					} else {
						if (!validator.alfanumericValidator(type.getName(), 3,
								20)) {
							throw new InvalidTypeException("Nome invalido!");
						}
						// }
					}
				}
				// persiste no banco o novo usuário
					 openSession();
				Type updatedType = typeDAO.update(type);
				closeSession();
				return updatedType;
			}
		}
		}
	}

	@Override
	public Type findByName(String name) {
		openSession();
		Type type = typeDAO.findByName(name);
		closeSession();
		return type;
	}
	
	public Type loadById(Long id) {
		openSession();
		Type type = typeDAO.load(id);
		closeSession();
		return type;
		
	}
}
